﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using WorkflowFramework;

namespace WorkflowFramework
{
    public class WorkFlowBuilder : IWorkFlowBuilder
    {
        public readonly List<IFlowStep> _steps;
        public WorkFlowBuilder()
        {
            _steps = new List<IFlowStep>();
        }
        public IWorkFlowBuilder AddStep(IFlowStep step)
        {
            _steps.Add(step);
            return this;
        }

        public IWorkFlowBuilder AddStep<TStep>() where TStep : IFlowStep, new()
        {
            return AddStep(new TStep());
        }

        public IWorkFlowBuilder AddStep(Func<IFlowStep> stepFactory)
        {
            return AddStep(stepFactory());
        }
        public IWorkFlowBuilder AddStep(string stepName, Func<Task<FlowStepResult>> executeAction)
        {
            return AddStep(new AnonymousFlowStep(stepName, executeAction));
        }
        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="steps"></param>
        /// <returns></returns>
        public IWorkFlowBuilder AddSteps(IEnumerable<IFlowStep> steps)
        {
            _steps.AddRange(steps);
            return this;
        }
        public IWorkFlowBuilder AddStepIf(IFlowStep step, Func<bool> condition)
        {
            if (condition())
            {
                AddStep(step);
            }
            return this;
        }

        public IWorkFlowExecutor Build()
        {
            return new WorkFlowExecutor(_steps);
        }

        /// <summary>
        /// 分支处理
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="trueBranch"></param>
        /// <param name="falseBranch"></param>
        /// <returns></returns>
        public IWorkFlowBuilder Branch(Func<bool> condition,Action<IWorkFlowBuilder> trueBranch,Action<IWorkFlowBuilder> falseBranch = null)
        {
            var trueBuilder = new WorkFlowBuilder();
            trueBranch?.Invoke(trueBuilder);

            var falseBuilder = new WorkFlowBuilder();
            falseBranch?.Invoke(falseBuilder);

            return AddStep(new BranchFlowStep(condition, trueBuilder.BuildInternal(), falseBuilder.BuildInternal()));
        }

        internal IWorkFlowExecutor BuildInternal()
        {
            return Build();
        }

        private class AnonymousFlowStep : FlowStepBase
        {
            private readonly Func<Task<FlowStepResult>> _executeAction;

            public AnonymousFlowStep(string stepName, Func<Task<FlowStepResult>> executeAction)
            {
                StepName = stepName;
                _executeAction = executeAction;
            }

            public override string StepName { get; }

            public override Task<FlowStepResult> ExecuteAsync() => _executeAction();
        }
    }
}
